#ifndef MEGAMAN_H
#define MEGAMAN_H

#include <GL/glut.h>
#include <cmath>

#include "Level.h"
#include "UtilFunctions.h"
#include "GlobalSettings.h"
#include "MathMisc.h"

class MegaMan
{
	public:
		friend class Camera;
		MegaMan();
		MegaMan(float x, float y, float z, Level * level);
		MegaMan(Position point, Level * level);
		void setMega(Position point, Level * level);

		void Update();

		void HandleInput();

		MegaMan & operator = (MegaMan * Mega)
		{
			location = Mega->location;
			velocity = Mega->velocity;
			return *this;
		}

	private:
		Level * curLevel;
		Position location;
		Position velocity;
		Position orientation;
		int cellX, cellY;
		float cameraMod;
		vector<Quad> Surroundings;
		bool isMoving;

		int shoulder, shoulder2, elbow, elbow2;
		bool setRun;

		void Move();
		bool CheckCell(int x, int y, float height);
		void GetSurroundings();

		void IdleAnimation();

};

MegaMan::MegaMan()
{ 
	isMoving = false; 
	cameraMod = 0;
	curLevel = 0;
	cellX = cellY = -1;
	shoulder = -85;
	shoulder2 = -85;
	elbow = 10;
	elbow2 = 10;
	setRun = true;
}

MegaMan::MegaMan(float x, float y, float z, Level * level)
{ 
	location(x, y, z);
	cellX = x != 0 ? x/CELLWIDTH : 0;
	cellY = z != 0 ? z/CELLWIDTH : 0;
	isMoving = false; 
	cameraMod = 0;
	curLevel = level;
	GetSurroundings();
	shoulder = -85;
	shoulder2 = -85;
	elbow = 10;
	elbow2 = 10;
	setRun = true;
}

MegaMan::MegaMan(Position point, Level * level)
{ 
	location = point;
	orientation.angle = location.angle;
	cellX = location.x != 0 ? location.x/CELLWIDTH : 0;
	cellY = location.z != 0 ? location.z/CELLWIDTH : 0;
	isMoving = false;
	cameraMod = 0; 
	curLevel = level;
	GetSurroundings();
	shoulder = -85;
	shoulder2 = -85;
	elbow = 10;
	elbow2 = 10;
	setRun = true;
}

void MegaMan::setMega(Position point, Level * level)
{
	location = point; 
	orientation.angle = location.angle;
	cellX = point.x != 0 ? point.x/CELLWIDTH : 0;
	cellY = point.z != 0 ? point.z/CELLWIDTH : 0;
	isMoving = false;
	cameraMod = 0; 
	curLevel = level;
	GetSurroundings();	
	shoulder = -85;
	shoulder2 = -85;
	elbow = 10;
	elbow2 = 10;
	setRun = true;
}

void MegaMan::HandleInput()
{
	float angle = 0;
	isMoving = true;
	orientation.angle = 0;
	if (KeyDownSpecial[0])
	{
		angle = 90;
		orientation.angle = 0;
	}
	else if (KeyDownSpecial[1])
	{
		angle = 270;
		orientation.angle = 180;
	}
	else
	{
		angle = 0;
		isMoving = false;
	}

	if (KeyDownSpecial[2] && !isMoving)
	{
		angle = 180;
		orientation.angle = 90;
		isMoving = true;
	}
	else if (KeyDownSpecial[3] && !isMoving)
	{
		angle = 0;
		orientation.angle = 270;
		isMoving = true;
	}
	else if (KeyDownSpecial[2] && isMoving)
	{
		orientation.angle += orientation.angle == 0 ? 45 : -45;
		angle += angle == 90 ? 45 : -45;
	}
	else if (KeyDownSpecial[3] && isMoving)
	{
		angle += angle == 270 ? 45 : -45;
		orientation.angle += orientation.angle == 180 ? 45 : -45;
	}

	velocity.angle = angle + cameraMod;
	orientation.angle += cameraMod;

	// ========================================

	bool forward = 1;
	bool reverse = 1;
	bool forward2 = 1;
	bool reverse2 = 1;
	if(KeyDown['f'])
	{
		if (setRun)
		{
			shoulder = -68; 
			shoulder2 = -113; 
			elbow = 60;
			setRun = false;
		}
		if (forward)
		{
			shoulder = (shoulder + 5) % 360;
			if (shoulder >= -45)
				forward = false;
		}

		if (forward2)
		{
			shoulder2 = (shoulder2 + 5) % 360;
			if (shoulder2 >= -45)
				forward2 = false;
		}

		if (!forward)
		{
			shoulder = (shoulder - 90) % 360;
		}

		if (!forward2)
		{
			shoulder2 = (shoulder2 - 90) % 360;
		}
	}
	if(KeyDown['z'])
	{
		shoulder = -60; 
		shoulder2 = -60; 
		elbow = 90;
	}
	if(KeyDown['x'])
	{
		shoulder = -85; 
		shoulder2 = -85; 
		elbow = 10;
	}
	if(KeyDown['c'])
	{
		shoulder = -68; 
		shoulder2 = -113; 
		elbow = 60;
		setRun = false;
	}
	if(KeyDown['r'])
	{
		elbow += 5;
	}
	if(KeyDown['t'])
	{
		shoulder2 += 5;
	}
}

void MegaMan::Update()
{
	// Play next animation frame from here.
	Move();

	IdleAnimation();
}

void MegaMan::Move()
{
	if (isMoving)
	{
		Position temp = location;
		int tCellX, tCellY;
		temp.x += MSPEED*sin(toRadian(velocity.angle));
		temp.z += MSPEED*cos(toRadian(velocity.angle));
		if(curLevel->GetCell(cellX, cellY).angle <= 60)
		{
			int orientation = curLevel->GetCell(cellX, cellY).orientation;
			if(orientation%90 == 0)
			{
				if(orientation == UP)
				{
					float x1 = temp.x;
					float y1 = temp.z;
					float x2 = temp.x;
					float y2 = curLevel->GetCell(cellX, cellY).TopLeft.z;
					float cellheight = curLevel->GetCell(cellX, cellY).TopLeft.y;
					float dist = distance(x1, y1, x2, y2);
					float angle = curLevel->GetCell(cellX, cellY).angle;
					temp.y += dist*cos(toRadian(angle));
					if (temp.y > cellheight)
						temp.y = cellheight;

				}
				if(orientation == DOWN)
				{
					float x1 = temp.x;
					float y1 = temp.z;
					float x2 = temp.x;
					float y2 = curLevel->GetCell(cellX, cellY).BottomLeft.z;
					float cellheight = curLevel->GetCell(cellX, cellY).BottomLeft.y;
					float dist = distance(x1, y1, x2, y2);
					float angle = curLevel->GetCell(cellX, cellY).angle;
					temp.y += dist*cos(toRadian(angle));
					if (temp.y > cellheight)
						temp.y = cellheight;

				}

			}
			else
			{

			}
			//temp.y += MSPEED*
		}

		tCellX = temp.x != 0 ? temp.x/CELLWIDTH : 0;
		tCellY = temp.z != 0 ? temp.z/CELLWIDTH : 0;

		if ( tCellX != cellX || tCellY != cellY)
		{
			if(CheckCell(tCellX, tCellY, temp.y))
			{
				cellX = tCellX;
				cellY = tCellY;
				GetSurroundings();	
				location = temp;
			}
		}
		else 
			location = temp;
	}
}

bool MegaMan::CheckCell(int x, int y, float height)
{
	if(height < curLevel->GetCell(x,y).avgheight)
		return (curLevel->GetCell(x,y).angle <= 45);
//	else if(height == curLevel->GetCell(x,y))
//		return true;
	return true;
}

void MegaMan::GetSurroundings()
{
	Surroundings.clear();
	Surroundings.resize(8);

	////cout << "=============================" << endl;
	// Top Left
	Surroundings[0] = curLevel->GetCell(cellX-1,cellY+1);
//	////cout << "Top Left:\t " << Surroundings[0].avgheight << "\t " << Surroundings[0].angle << "\t " << Surroundings[0].orientation << endl;
	// Top
	Surroundings[1] = curLevel->GetCell(cellX,cellY+1);
//	////cout << "Top:\t\t " << Surroundings[1].avgheight << "\t " << Surroundings[1].angle << "\t " << Surroundings[1].orientation << endl;
	// Top Right
	Surroundings[2] = curLevel->GetCell(cellX+1,cellY+1);
//	////cout << "Top Right:\t " << Surroundings[2].avgheight << "\t " << Surroundings[2].angle << "\t " << Surroundings[2].orientation << endl;
	// Right
	Surroundings[3] = curLevel->GetCell(cellX+1,cellY);
//	////cout << "Right:\t\t " << Surroundings[3].avgheight << "\t " << Surroundings[3].angle << "\t " << Surroundings[3].orientation << endl;
	// Bottom Right
	Surroundings[4] = curLevel->GetCell(cellX+1,cellY-1);
	////cout << "Bottom Right:\t " << Surroundings[4].avgheight << "\t " << Surroundings[4].angle << "\t " << Surroundings[4].orientation << endl;
	// Bottom
	Surroundings[5] = curLevel->GetCell(cellX,cellY-1);
	////cout << "Bottom:\t\t " << Surroundings[5].avgheight << "\t " << Surroundings[5].angle << "\t " << Surroundings[5].orientation << endl;
	// Bottom Left
	Surroundings[6] = curLevel->GetCell(cellX-1,cellY-1);
	////cout << "Bottom Left:\t " << Surroundings[6].avgheight << "\t " << Surroundings[6].angle << "\t " << Surroundings[6].orientation << endl;
	// Left
	Surroundings[7] = curLevel->GetCell(cellX-1,cellY);
	////cout << "Left:\t\t " << Surroundings[7].avgheight << "\t " << Surroundings[7].angle << "\t " << Surroundings[7].orientation << endl;

	////cout << "=============================" << endl;
}

void MegaMan::IdleAnimation()
{
	glTranslatef(location.x, location.y, location.z);
	glRotatef(orientation.angle, 0, 1, 0);


	//right arm
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (4.2+0.4)*FEETtoPIXIL, 1.2*FEETtoPIXIL);		  //M1 = T-1
	glRotatef ((GLfloat) shoulder, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M3 = T-1RsT+1

	glPushMatrix();				  //Save M3
	glScalef (1.5, 0.5, 0.5);			  //M4 = T-1RsT+1S
	glColor3f(0.8f,0.8f,1.0f);             //megaman color
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M3 = T-1RsT+1
	glTranslatef (0.6*FEETtoPIXIL, 0.0, 0);		  //M5 = T-1RsT+1T+1
	glRotatef ((GLfloat) elbow, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M7 = T-1RsT+1T+1ReT+1

	glPushMatrix();				  //Save M7
	glScalef (1.5, 0.5, 0.5);
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M7 

	glPopMatrix();				  //Restore M0

	//left arm
	glPushMatrix();			  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (4.2+0.4)*FEETtoPIXIL, -1.2*FEETtoPIXIL);		  //M1 = T-1
	glRotatef ((GLfloat) shoulder2, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M3 = T-1RsT+1

	glPushMatrix();				  //Save M3
	glScalef (1.5, 0.5, 0.5);			  //M4 = T-1RsT+1S
	glColor3f(0.8f,0.8f,1.0f);             //megaman color
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M3 = T-1RsT+1
	glTranslatef (0.6*FEETtoPIXIL, 0.0, 0);		  //M5 = T-1RsT+1T+1
	glRotatef ((GLfloat) elbow2, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M7 = T-1RsT+1T+1ReT+1

	glPushMatrix();				  //Save M7
	glScalef (1.5, 0.5, 0.5);
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M7 

	glPopMatrix();				  //Restore M0

	//right leg
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (2.4+0.4)*FEETtoPIXIL, 0.45*FEETtoPIXIL);		  //M1 = T-1
	glRotatef ((GLfloat) shoulder2, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M3 = T-1RsT+1

	glPushMatrix();				  //Save M3
	glScalef (1.5, 0.6, 0.6);			  //M4 = T-1RsT+1S
	glColor3f(0.8f,0.8f,1.0f);             //megaman color
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M3 = T-1RsT+1
	glTranslatef (0.6*FEETtoPIXIL, 0.0, 0.0);		  //M5 = T-1RsT+1T+1
	glRotatef ((GLfloat) -elbow2, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M7 = T-1RsT+1T+1ReT+1

	glPushMatrix();				  //Save M7
	glScalef (1.5, 0.6, 0.6);
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M7 

	glPopMatrix();				  //Restore M0

	//left leg
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (2.4+0.4)*FEETtoPIXIL, -0.45*FEETtoPIXIL);		  //M1 = T-1
	glRotatef ((GLfloat) shoulder2, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M3 = T-1RsT+1

	glPushMatrix();				  //Save M3
	glScalef (1.5, 0.6, 0.6);			  //M4 = T-1RsT+1S
	glColor3f(0.8f,0.8f,1.0f);             //megaman color
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M3 = T-1RsT+1
	glTranslatef (0.6*FEETtoPIXIL, 0.0, 0.0);		  //M5 = T-1RsT+1T+1
	glRotatef ((GLfloat) -elbow, 0.0, 0.0, 1.0);
	glTranslatef (0.75*FEETtoPIXIL, 0.0, 0.0);		  //M7 = T-1RsT+1T+1ReT+1

	glPushMatrix();				  //Save M7
	glScalef (1.5, 0.6, 0.6);
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);

	glPopMatrix();				  //Restore M7 

	glPopMatrix();				  //Restore M0


	//head
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (4.6+0.5-0.2+0.4)*FEETtoPIXIL, 0*FEETtoPIXIL);		  //M1 = T-1
	glScalef (0.9, 0.7, 0.6);
	glColor3f(1.0f,0.9f,0.9f);
	glutSolidSphere (FEETtoPIXIL, 12, 12);
	glPopMatrix();

	//chest
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (4.4-0.2+0.4)*FEETtoPIXIL, 0*FEETtoPIXIL);		  //M1 = T-1
	glScalef (1.4, 0.7, 2.1);			  //M4 = T-1RsT+1S
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);
	glPopMatrix();

	//torso

	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (3.3+0+0.4)*FEETtoPIXIL, 0*FEETtoPIXIL);		  //M1 = T-1
	glScalef (0.8, 1.2, 1.3);			  //M4 = T-1RsT+1S
	glColor3f(0.8f,0.8f,1.0f);             //megaman color
	glutSolidCube (FEETtoPIXIL);
	glPopMatrix();

	//hips
	glPushMatrix();				  //Save M0
	glTranslatef (0.5*FEETtoPIXIL, (2.05+0.5+0.4)*FEETtoPIXIL, 0*FEETtoPIXIL);		  //M1 = T-1
	glScalef (1.2, 0.65, 1.5);			  //M4 = T-1RsT+1S
	glColor3f(0.5f,0.5f,1.0f);
	glutSolidCube (FEETtoPIXIL);
	glPopMatrix();
}

#endif
